/*
 * Copyright (C) 2012 Richard Schilling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dalvik.vm.analysis;

import java.util.BitSet;
import java.util.LinkedList;
import java.util.Stack;

import com.android.dx.io.instructions.DecodedInstruction;

/**
 * A DecodedInstruction with additonal data attached to it that is useful to
 * code analysis.
 * <p>
 * A Dalvik instruction, or code unit that resides in
 * <code>code_data_item</> in a DEX File.
 * 
 * <p>
 * There are many package scoped members and methods because they don't need to 
 * be used outside this package.  This lets other classes in this package work on 
 * them without affecting them.
 * 
 * 
 * <p>All instructions extends this base class. It contains members and method that
 * have package scope so that it can be analyzed. A class that represents an
 * instruction that gets analyzed by other classes in this package. This
 * contents of this class are required by CodeVerify and contains members and
 * methods that have package scope.
 * 
 * @author rschilling
 */
public class AnalyzableInstruction {
    /**
     * The maximum number of short values that any instruction will be encoded into.
     */
    public static final int MAX_SIZE = 10; // TODO make sure this number is accurate.

    /**
     * AnalyzableInstruction widths and flags, one entry per code unit.
     */

    /* package */int insnFlags = 0;

    private RegisterLine registerLine = null;
    private DecodedInstruction refersTo;

    public AnalyzableInstruction(DecodedInstruction refersTo) {
        
        if (refersTo == null)
            throw new IllegalArgumentException("refersTo cannot be null.");
        
        this.refersTo = refersTo;
    }
    
    public DecodedInstruction asDecodedInstruction(){
        return refersTo;
    }

    public RegisterLine getRegisterLine() {
        if (registerLine == null)
            registerLine = new RegisterLine();
        return registerLine;

    }

    public void clearRegisterLine() {
        registerLine = null;
    }

    public boolean hasRegisterLine() {
        return registerLine != null ? true : false;
    }

    /**
     * During verification, we associate one of these with every "interesting"
     * instruction. We track the status of all registers, and (if the method
     * has any monitor-enter instructions) maintain a stack of entered monitors
     * (identified by code unit offset).
     * <p>
     * If live-precise register maps are enabled, the "liveRegs" vector will be
     * populated. Unlike the other lists of registers here, we do not track the
     * liveness of the method result register (which is not visible to the GC).
     */
    public class RegisterLine {

        private RegisterLine() {}

        public AnalyzableInstruction getInstruction() {
            return AnalyzableInstruction.this;
        }

        /**
         * The types of registers associated with this instruction.
         */
        public LinkedList<RegisterType> regTypes = new LinkedList<RegisterType>();

        /**
         * A bit vector indicating which entries in the monitor stack are
         * associated with this register. The low bit corresponds to the stack's
         * bottom-most entry.
         */
        public BitSet monitorEntries = new BitSet();

        Stack<BitSet> monitorStack = new Stack<BitSet>();

        public BitSet liveRegs;

    };

}
